import wx
from ui_elements.panel_copy import attribute_control_copy as copy


CTRL_HIGHLIGHT_COLOUR = "#CDCD00"


class AttributeControl(wx.Panel):
    def __init__(self, parent, control_info):
        wx.Panel.__init__(self, parent)
        self.control_info = copy(control_info)

        self.parent = parent
        self.displayable = False
        self.ignore_value_update = False
        
        if 'conversion' in control_info:
            self.conversion = control_info['conversion']
            self.r_conversion = {}
            for k,v in self.conversion.iteritems():
                self.r_conversion[v] = k
        else:
            self.conversion = {}
            self.r_conversion = {}
        
        self.content = wx.BoxSizer(wx.HORIZONTAL)
        self.SetSizer(self.content)
        
        
    # Some convenience functions for sub-classes
    def insert_caption(self, text, text_align=wx.ALIGN_CENTER):
        self.caption = wx.StaticText(self, -1, '%s:' % text)
        self.content.Add(self.caption, 0, text_align | wx.ALL, 5)
    def insert_control(self, control):
        self.control = control
        self.content.Add(control, 1, wx.EXPAND | wx.ALIGN_BOTTOM | wx.ALL, 5)
    def setup_complete(self):
        if 'tip' in self.control_info:
            self.set_tooltip(self.control_info['tip'])
        self.Layout()
    
    
    def set_module(self, module_info, module_values):
        key = self.control_info['key']
        
        if key in module_info['required'] or key in module_info['optional']:
            self.displayable = True
        else:
            self.displayable = False
        
        if key in module_info['required']:
            self.set_background_colour(CTRL_HIGHLIGHT_COLOUR)
        else:
            self.set_background_colour(None)

        if key in module_values:
            self.update_displayed_value(module_values[key])

    
    def update_displayed_value(self, value):
        # To be implemented in sub-classes
        self.control.SetValue(self.convert_internal_to_ui(value))
    
    
    def set_tooltip(self, text):
        # Can be overridden in more complex cases
        self.control.SetToolTipString(text)
    
    
    def set_background_colour(self, colour):
        # Can be overridden in more complex cases
        self.control.SetBackgroundColour(colour)


    def set_displayed_value(self, value):
        # Can be overridden in more complex cases
        self.control.SetValue(self.convert_internal_to_ui(value))
        
        
    def should_display(self):
        return self.displayable
    
    
    def set_handler(self, item_id, event, handler=None):
        if handler == None:
            handler = self.handler_value_changed
        self.Bind(event, handler, id=item_id)
    
    
    def handler_value_changed(self, event):
        # Can be overridden in more complex cases
        self.evt_value_updated(self.control_info['key'], self.control.GetValue(), self)
    
    
    def evt_value_updated(self, key, value, sender=None):
        if self.ignore_value_update:
            self.ignore_value_update = False # We only ever want to ignore one
            return
    
        if key != self.control_info['key']:
            return
        
        # Pass the event along the chain
        if sender == self:
            # A new value was typed
            value = self.convert_ui_to_internal(value)
            self.parent.evt_value_updated(key, value, self)
        else:
            # The change has been forced from elsewhere
            value = self.convert_internal_to_ui(value)
            self.update_displayed_value(value)
    
    
    def convert_ui_to_internal(self, value):
        return self.r_conversion.get(value, value)
    def convert_internal_to_ui(self, value):
        return self.conversion.get(value, value)
    
    def reset_displayed_value(self):
        self.ignore_value_update = True
        self.control.reset_value()



import ui_elements.controls.textctrlborder as tcb
import ui_elements.controls.comboboxborder as cbb
import ui_elements.controls.checkboxborder as chb


class TextControl(AttributeControl):
    def __init__(self, parent, control_info):
        AttributeControl.__init__(self, parent, control_info)
        self.insert_caption(control_info['desc'])
        control = tcb.TextCtrlBorder(self, control_info['id'])
        if 'readonly' in control_info and control_info['readonly'] == True: control.textctrl.Enable(False)
        self.insert_control(control)
        self.setup_complete()
        self.set_handler(control_info['id'], wx.EVT_TEXT)


class BigTextControl(AttributeControl):
    def __init__(self, parent, control_info):
        AttributeControl.__init__(self, parent, control_info)
        control = tcb.TextCtrlBorder(self, control_info['id'], style=wx.TE_MULTILINE|wx.TE_NOHIDESEL, size=(-1,80))
        self.insert_caption(control_info['desc'], text_align=wx.ALIGN_TOP)
        self.insert_control(control)
        self.setup_complete()
        self.set_handler(control_info['id'], wx.EVT_TEXT)


class ListControl(AttributeControl):
    def __init__(self, parent, control_info):
        AttributeControl.__init__(self, parent, control_info)
        control = cbb.ComboBoxBorder(self, control_info['id'], choices=control_info['options'], style=wx.CB_READONLY)
        self.insert_caption(control_info['desc'])
        self.insert_control(control)
        self.setup_complete()
        self.set_handler(control_info['id'], wx.EVT_COMBOBOX)


class YesNoControl(AttributeControl):
    def __init__(self, parent, control_info):
        AttributeControl.__init__(self, parent, control_info)
        control = chb.CheckboxBorder(self, control_info['id'])
        if 'readonly' in control_info and control_info['readonly'] == True: control.checkbox.Enable(False)
        self.insert_caption(control_info['desc'])
        self.insert_control(control)
        self.setup_complete()
        self.set_handler(control_info['id'], wx.EVT_CHECKBOX)
    def convert_ui_to_internal(self, value):
        return int(value)
    def convert_internal_to_ui(self, value):
        return bool(int(value))
        
